#include "ImageProcessor.h"
#include "authorizationtiming.h"
#include "networkmanager.h"
#include "qtconcurrentrun.h"
#include "source/authorizationtool.h"
#include "source/logger.h"
#include "source/tools.h"
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <QCryptographicHash>
#include <QByteArray>
#include <QMessageAuthenticationCode>
#include <QDataStream>


AuthorizationTiming::AuthorizationTiming(QObject *parent)
    : QObject(parent), m_totalTime(0), m_remainingTime(-1),m_running(false)
{
    secret_key = NetworkManager::instance()->serialnumber().toUtf8();


}

void AuthorizationTiming::openAuthorizetion()
{
    LogDebug << "AuthorizationTiming::openAuthorizetion" ;
    loadTimeFromFile();


    QString exceptionFilePath = "/tmp/qt_app_exception";

    // 使用QProcess执行命令来删除异常文件
    QProcess process;
    QStringList arguments;
    arguments << "-c" << QString("rm -f %1").arg(exceptionFilePath);

    process.start("/bin/bash", arguments);
    process.waitForFinished(); // 等待命令执行完成

    int exitCode = process.exitCode();
    if (exitCode == 0) {
        qDebug() << "Exception file deleted successfully.";
    } else {
        qDebug() << "Failed to delete the exception file. Exit code:" << exitCode;
    }


    if (m_remainingTime == -520)
    {
        expirationdateTimer.stop();
        return;
    }
    if(m_running==false)
    {
        m_running = true;
        m_future = QtConcurrent::run([this]() { updateCountdown(); });
    }
    expirationdateTimer.setInterval(5000); // 设置时间间隔为5000毫秒（5秒）
    expirationdateTimer.setSingleShot(false); // 设置为重复触发
    connect(&expirationdateTimer, &QTimer::timeout, this, &AuthorizationTiming::updateCountdown);
    expirationdateTimer.start(); // 启动定时器

}

int AuthorizationTiming::authorizationuser(const QString &plainText)
{
    // LogDebug  << "AuthorizationTiming::authorizationuser:" << plainText;
    QString serial = customEncrypt(NetworkManager::instance()->serialnumber() ,secret);
    //qDebug() << "NetworkManager::instance()->serialnumber() :" << NetworkManager::instance()->serialnumber() << "serial:" <<serial;
    //qDebug() << "customEncrypt" << serial;

    if (plainText == serial) {
        qDebug() << "The strings are identical.";
        return true;
    } else {
        // 字符串不同
        qDebug() << "The strings are different.";
        return false;
    }
}

int AuthorizationTiming::authorizationuserBytime(const QString &plainText)
{
    std::pair<std::string, unsigned int> decrypted = decrypt(plainText.toStdString());
    qInfo() << "Decrypted Sequence: " << QString::fromStdString(decrypted.first) ; // 应为"ABCDEF"
    qInfo() << "Decrypted Timestamp: " << decrypted.second ; // 应为1633072800
    if(decrypted.first.empty())
        return -1;

    QString serialNumber = NetworkManager::instance()->serialnumber();
    if(serialNumber.left(6).toUpper() == QString::fromStdString(decrypted.first).toUpper())
    {
        // 判断 decrypted.second 是否在24120100和99120100之间
        if(static_cast<int>(decrypted.second) == 520)
        {
            setTotalTime(-520);
            return -520;
        }

        if(decrypted.second >= 24120100 && decrypted.second <= 99120100)
        {
            setTotalTime(decrypted.second);
            return decrypted.second;  // 满足条件
        }
    }
    qWarning() << "serialNumber.left(6).toUpper() !- = it ";
    return -1;
}

void AuthorizationTiming::setTotalTime(int seconds)
{
    LogDebug << "AuthorizationTiming::setTotalTime" << seconds;
    if(seconds == -520)
    {
        m_remainingTime = -520;
        saveTimeToFile();
        LogDebug << "AuthorizationTiming::setTotalTime unfreeze" ;
        return;
    }
    if(seconds < 24010000)
    {
        seconds*=60;
    }
    m_totalTime = seconds;
    m_remainingTime = seconds;
    saveTimeToFile();
    emit remainingTimeChange();


    // if(m_running==false)
    // {
    //     m_running = true;
    //     m_future = QtConcurrent::run([this]() { updateCountdown(); });
    // }
}

void AuthorizationTiming::resetTotalTime(int seconds)
{
    setTotalTime(seconds);
    saveTimeToFile();
}

void AuthorizationTiming::startCountdown()
{
    m_timer->start(1000); // 每秒更新一次

}

void AuthorizationTiming::stopCountdown()
{
    m_timer->stop();
    saveTimeToFile();
}

void AuthorizationTiming::loadTimeFromFile()
{
    QFile file(timing_dataPath);
    if (file.open(QIODevice::ReadOnly)) {
        QByteArray encryptedData = file.readAll();
        file.close();
        m_remainingTime = decryptTime(encryptedData);  // 直接使用 QByteArray

        LogDebug << "AuthorizationTiming::loadTimeFromFile :" << m_remainingTime;
    } else {
        LogDebug << "AuthorizationTiming::loadTimeFromFile not exist";
        m_remainingTime = -1;
    }
    emit remainingTimeChange();
}

void AuthorizationTiming::saveTimeToFile()
{
    QFile file(timing_dataPath);
    if (file.open(QIODevice::WriteOnly)) {
        QByteArray encryptedData = encryptTime(m_remainingTime);
        file.write(encryptedData);
        file.close();
    } else {
        LogDebug << "AuthorizationTiming::saveTimeToFile failed to open file";
    }
}


void AuthorizationTiming::updateCountdown()
{
    // qInfo() << "m_remainingTime" << m_remainingTime;
    if(m_remainingTime>24000000)
    {
        // 解析 m_remainingTime
        int year = m_remainingTime / 1000000;           // 获取年份部分
        int month = (m_remainingTime / 10000) % 100;    // 获取月份部分
        int day = (m_remainingTime / 100) % 100;        // 获取日期部分
        int hour = m_remainingTime % 100;               // 获取小时部分

        // 创建目标时间对象
        QDateTime targetTime(QDate(year + 2000, month, day), QTime(hour, 0)); // 年份需要加上2000

        // 获取当前时间
        QDateTime currentTime = QDateTime::currentDateTime();

        // qDebug() << "当前时间: " << currentTime.toString();
        // qDebug() << "目标时间: " << targetTime.toString();

        // 比较当前时间和目标时间
        if (currentTime > targetTime) {
            qDebug() << "AuthorizationTiming:: m_remainingTime < 0";
            emit authorizationExpires();  // 发出倒计时结束信号
        }
    }
    else if(m_remainingTime!= -520)
    {
        m_remainingTime-=5;
        secondsElapsed+=5;
        if(ImageProcessor::getInstance().selectedStep() == ImageProcessor::MeauAbout)
        {
            emit remainingTimeChange();
        }


        if (secondsElapsed >= 60) {
            // 每60秒保存一次倒计时数据
            qDebug() << "Saving time to file...";
            secondsElapsed = 0;
            saveTimeToFile();
            // 调用保存函数，如 saveTimeToFile()
        }

        if (m_remainingTime <= 0) {
            LogDebug << "AuthorizationTiming:: m_remainingTime <0";
            emit authorizationExpires(); // 发出倒计时结束信号
            m_running = false;
        }
    }
}


QByteArray AuthorizationTiming::encryptTime(int time)
{
    // 生成加密密钥
    QByteArray key = QCryptographicHash::hash(secret_key, QCryptographicHash::Sha256);
    //qDebug() << "Generated key from secret_key:" << key.toHex();

    // 生成随机IV
    unsigned char iv[AES_BLOCK_SIZE];
    RAND_bytes(iv, AES_BLOCK_SIZE);
    QByteArray ivBackup(reinterpret_cast<char*>(iv), AES_BLOCK_SIZE); // 备份 IV
    //qDebug() << "Generated IV:" << ivBackup.toHex();

    // 将时间转换为字节数组
    QByteArray data;
    QDataStream stream(&data, QIODevice::WriteOnly);
    stream << time;
    //qDebug() << "Original time data:" << data.toHex();

    // 填充数据
    int dataSize = data.size();
    int paddingSize = AES_BLOCK_SIZE - (dataSize % AES_BLOCK_SIZE);
    data.append(QByteArray(paddingSize, paddingSize)); // PKCS#7 padding
    //qDebug() << "Data with PKCS#7 padding:" << data.toHex();

    // 初始化加密
    QByteArray encryptedData(data.size(), '\0');
    AES_KEY encryptKey;
    AES_set_encrypt_key(reinterpret_cast<const unsigned char*>(key.constData()), 256, &encryptKey);
    AES_cbc_encrypt(reinterpret_cast<const unsigned char*>(data.constData()), reinterpret_cast<unsigned char*>(encryptedData.data()), data.size(), &encryptKey, iv, AES_ENCRYPT);
    //qDebug() << "Encrypted data:" << encryptedData.toHex();

    // 生成HMAC
    QByteArray hmac = QMessageAuthenticationCode::hash(encryptedData, key, QCryptographicHash::Sha256);
    //qDebug() << "Generated HMAC:" << hmac.toHex();

    // 组合 IV、HMAC 和加密数据
    QByteArray combined = ivBackup + hmac + encryptedData;
    //qDebug() << "Combined encrypted data with IV and HMAC:" << combined.toHex();

    // 返回组合后的数据
    return combined;
}

int AuthorizationTiming::decryptTime(const QByteArray &data)
{
    //qDebug() << "Starting decryption process... : "<< data.toHex();

    QByteArray key = QCryptographicHash::hash(secret_key, QCryptographicHash::Sha256); // 加密密钥
    //qDebug() << "Generated key from secret_key:" << key.toHex();

    if (data.size() < AES_BLOCK_SIZE + 32) {
        qWarning() << "Data is too short, possibly corrupted.";
        return -1;
    }

    // 提取IV
    unsigned char iv[AES_BLOCK_SIZE];
    memcpy(iv, data.left(AES_BLOCK_SIZE).constData(), AES_BLOCK_SIZE);
    //qDebug() << "Extracted IV:" << QByteArray(reinterpret_cast<char*>(iv), AES_BLOCK_SIZE).toHex();

    // 提取HMAC和加密数据
    QByteArray hmac = data.mid(AES_BLOCK_SIZE, 32);
    QByteArray encryptedData = data.mid(AES_BLOCK_SIZE + 32);
    //qDebug() << "Extracted HMAC:" << hmac.toHex();
    //qDebug() << "Extracted encrypted data:" << encryptedData.toHex();

    // 验证HMAC
    QByteArray calculatedHmac = QMessageAuthenticationCode::hash(encryptedData, key, QCryptographicHash::Sha256);
    if (hmac != calculatedHmac) {
        qWarning() << "Data integrity check failed. HMAC mismatch.";
        return -1; // 数据完整性验证失败
    }
    //qDebug() << "HMAC verification passed.";

    // 解密数据
    QByteArray decryptedData(encryptedData.size(), '\0');
    AES_KEY decryptKey;
    AES_set_decrypt_key(reinterpret_cast<const unsigned char*>(key.constData()), 256, &decryptKey);
    AES_cbc_encrypt(reinterpret_cast<const unsigned char*>(encryptedData.constData()), reinterpret_cast<unsigned char*>(decryptedData.data()), encryptedData.size(), &decryptKey, iv, AES_DECRYPT);
    //qDebug() << "Decryption completed. Decrypted data (before removing padding):" << decryptedData.toHex();

    // 去除填充
    int paddingSize = decryptedData.at(decryptedData.size() - 1);
    if (paddingSize < 1 || paddingSize > AES_BLOCK_SIZE) {
        qWarning() << "Invalid padding size.";
        return -1;
    }
    decryptedData.chop(paddingSize); // 去除填充
    qDebug() << "Removed padding. Decrypted data:" << decryptedData.toHex();

    // 解析解密后的数据
    QDataStream stream(decryptedData);
    int time;
    stream >> time;
    qDebug() << "Extracted time from decrypted data:" << time;

    if ((time < 0 && time !=-520) || time > m_maxtotail) {
        qWarning() << "Decryption result is invalid. Time value out of range.";
        return -1; // 解密结果无效
    }

    qDebug() << "Decryption successful. Returning time:" << time;
    return time;
}

